package org.example.infrastructure.persistent.repository;

import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.rebate.model.aggregate.BehaviorRebateAggregate;
import org.example.domain.rebate.model.entity.BehaviorRebateOrderEntity;
import org.example.domain.rebate.model.valobj.BehaviorTypeVO;
import org.example.domain.rebate.model.valobj.DailyBehaviorRebateVO;
import org.example.domain.rebate.repository.IRebateRepository;
import org.example.domain.task.model.entity.TaskEntity;
import org.example.infrastructure.event.EventPublisher;
import org.example.infrastructure.persistent.dao.IDailyBehaviorRebateDao;
import org.example.infrastructure.persistent.dao.ITaskDao;
import org.example.infrastructure.persistent.dao.IUserBehaviorRebateOrderDao;
import org.example.infrastructure.persistent.po.DailyBehaviorRebate;
import org.example.infrastructure.persistent.po.Task;
import org.example.infrastructure.persistent.po.UserBehaviorRebateOrder;
import org.example.types.enums.ResponseCode;
import org.example.types.exception.AppException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Repository
@Slf4j
public class RebateRepository implements IRebateRepository {

    @Resource
    private IDailyBehaviorRebateDao dailyBehaviorRebateDao;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private IDBRouterStrategy dbRouter;


    @Resource
    private ITaskDao taskDao;

    @Resource
    private IUserBehaviorRebateOrderDao userBehaviorRebateOrderDao;

    @Resource
    private EventPublisher eventPublisher;

    /**
     * 查询用户行为返利配置列表
     * 一个行为对应多种返利配置
     * @param behaviorTypeVO 返利类型
     * @return 返利配置列表
     */
    @Override
    public List<DailyBehaviorRebateVO> queryDailyBehaviorRebatesByType(BehaviorTypeVO behaviorTypeVO) {
        String behaviorType= behaviorTypeVO.getCode();

        List<DailyBehaviorRebate> dailyBehaviorRebates = dailyBehaviorRebateDao.queryDailyBehaviorRebateByBehaviorType(behaviorType);
        List<DailyBehaviorRebateVO> dailyBehaviorRebateVOS = new ArrayList<>();

        for (DailyBehaviorRebate dailyBehaviorRebate : dailyBehaviorRebates){
            DailyBehaviorRebateVO dailyBehaviorRebateVO = DailyBehaviorRebateVO.builder()
                        .behaviorType(dailyBehaviorRebate.getBehaviorType())
                        .rebateDesc(dailyBehaviorRebate.getRebateDesc())
                        .rebateType(dailyBehaviorRebate.getRebateType())
                        .rebateConfig(dailyBehaviorRebate.getRebateConfig())
                        .build();

            dailyBehaviorRebateVOS.add(dailyBehaviorRebateVO);

        }

        return dailyBehaviorRebateVOS;
    }

    /**
     * 保存返利记录至数据库
     * 保存任务流水记录
     * 发送mq消息
     * @param behaviorRebateAggregates 聚合对象 : 返利记录同任务流水做事务保证消息可靠不丢失
     */
    @Override
    public void saveRebateRecord(List<BehaviorRebateAggregate> behaviorRebateAggregates) {

        for (BehaviorRebateAggregate behaviorRebateAggregate: behaviorRebateAggregates){
            BehaviorRebateOrderEntity behaviorRebateOrderEntity = behaviorRebateAggregate.getBehaviorRebateOrderEntity();
            TaskEntity taskEntity = behaviorRebateAggregate.getTaskEntity();
            String userId = behaviorRebateAggregate.getUserId();

            UserBehaviorRebateOrder userBehaviorRebateOrder = new UserBehaviorRebateOrder();
            userBehaviorRebateOrder.setUserId(behaviorRebateOrderEntity.getUserId());
            userBehaviorRebateOrder.setOrderId(behaviorRebateOrderEntity.getOrderId());
            userBehaviorRebateOrder.setBehaviorType(behaviorRebateOrderEntity.getBehaviorType());
            userBehaviorRebateOrder.setRebateDesc(behaviorRebateOrderEntity.getRebateDesc());
            userBehaviorRebateOrder.setRebateType(behaviorRebateOrderEntity.getRebateType());
            userBehaviorRebateOrder.setRebateConfig(behaviorRebateOrderEntity.getRebateConfig());
            userBehaviorRebateOrder.setOutBusinessNo(behaviorRebateOrderEntity.getOutBusinessNo());
            userBehaviorRebateOrder.setBizId(behaviorRebateOrderEntity.getBizId());

            Task task = Task.builder()
                        .userId(taskEntity.getUserId())
                        .topic(taskEntity.getTopic())
                        .messageId(taskEntity.getMessageId())
                        .message(taskEntity.getMessage())
                        .state(taskEntity.getState().getCode())
                        .build();


            try {
                dbRouter.doRouter(userId);
                transactionTemplate.execute(status -> {
                    try {
                        userBehaviorRebateOrderDao.insert(userBehaviorRebateOrder);
                        taskDao.insert(task);
                        return 1;
                    } catch (DuplicateKeyException e) {
                        log.info("唯一索引冲突");
                        status.setRollbackOnly();
                        throw new AppException(ResponseCode.INDEX_DUP.getCode(), e);
                    }
                });
            } finally {
                dbRouter.clear();
            }

            //发送mq消息
            try {
                eventPublisher.publish(task.getTopic() ,task.getMessage());
                taskDao.updateTaskSendMessageCompleted(task);
            } catch (Exception e) {
                taskDao.updateTaskSendMessageFail(task);
            }

        }

    }

    @Override
    public List<BehaviorRebateOrderEntity> queryRebateOrderByOutBusinessNo(String userId, String outBusinessNo) {

        List<BehaviorRebateOrderEntity> BehaviorRebateOrderEntities = new ArrayList<>();
        List<UserBehaviorRebateOrder> userBehaviorRebateOrders = userBehaviorRebateOrderDao.queryRebateOrderByOutBusinessNo(UserBehaviorRebateOrder.builder()
                .outBusinessNo(outBusinessNo)
                .userId(userId)
                .build());

        for (UserBehaviorRebateOrder userBehaviorRebateOrder:userBehaviorRebateOrders){
            BehaviorRebateOrderEntity behaviorRebateOrderEntity = BehaviorRebateOrderEntity.builder()
                        .userId(userBehaviorRebateOrder.getUserId())
                        .orderId(userBehaviorRebateOrder.getOrderId())
                        .behaviorType(userBehaviorRebateOrder.getBehaviorType())
                        .rebateDesc(userBehaviorRebateOrder.getRebateDesc())
                        .rebateType(userBehaviorRebateOrder.getRebateType())
                        .rebateConfig(userBehaviorRebateOrder.getRebateConfig())
                        .bizId(userBehaviorRebateOrder.getBizId())
                        .outBusinessNo(userBehaviorRebateOrder.getOutBusinessNo())
                        .build();
            BehaviorRebateOrderEntities.add(behaviorRebateOrderEntity);
        }
        return BehaviorRebateOrderEntities;
    }
}
